package com.cloud.springcloudribbon.consumer;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.ObservableExecutionMode;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 这里用到了 Hystrix 里面的注解。也用到了同步和异步。
 * 这里简单演示了下 Hystrix
 * weiximei on 2018/5/6
 */
@Service
public class HelloService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 这个@HystrixCommand注解表示，我用helloService这个方法发送请求
     *  fallbackMethod表示服务降级
     * @return
     */
    // 这个注解里面还可以加个 ignoreExceptions = xxx.class 参数，表示我忽略某个异常，忽略后就表示我这服务不会让它降级
    // 这个注解里面还可以加个 observableExecutionMode = ObservableExecutionMode.EAGER 参数，表示观察者模式命令的执行方式
    @HystrixCommand(fallbackMethod = "helloFallBack")
    public String helloService() throws ExecutionException, InterruptedException {
        // 获取这个服务，并把结果返回出去
        // 请求 HELLO-SERVICE 服务中心，然后就会获取到 HELLO-SERVICE 服务上注册好的客户端列表,
        // 然后根据这个列表进行均很负载算法得到一个Eureka客户端的连接
        // 这个请求实际上是网络IO，是个堵塞的。也就是我这段代码的后面还有代码，就不会继续向下执行，要等到返回结果后再继续执行
        // 如果想让这段代码下面的代码继续执行就要使用异步的IO
        //return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();

        // 使用异步IO方式
        Future<String> future = new AsyncResult<String>() {
            @Override
            public String invoke() {
                return restTemplate.getForEntity("http://HELLO-SERVICE/hello",String.class).getBody();
            }
        };
        return future.get();
    }

    /**
     * 上面的注解调用这个方法，表示这个方法为服务器降级方法。
     * 当上面的请求，无法请求的时候，就会返回这个方法
     *
     * @param throwable 异常，我们可以拿到出现问题的异常
     * @return
     */
    public String helloFallBack(Throwable throwable){
        return "error";
    }











}
